using System;
using NUnit.Framework;
using ValidationFramework.Reflection;
#if (!SILVERLIGHT && !WindowsCE)
using ValidationFramework.Web.ASP;
#endif

namespace ValidationFramework.Tests
{
    public sealed class CompareStringRuleTest
    {

        const string expectedValueToCompare = "expectedValueToCompare";
        const CompareOperator expectedCompareOperator = CompareOperator.GreaterThan;
        const string expectedErrorMessage = "EXPECTEDERRORMESSAGE";
        const string expectedRuleSet = "EXPECTEDRULESET";

        [TestFixture]
        public class Construction
        {
            [Test]
            public void Simple1()
            {
                var rule = new CompareRule<string>(expectedValueToCompare, expectedCompareOperator);
                Assert.AreEqual(expectedValueToCompare, rule.ValueToCompare);
                Assert.AreEqual(expectedCompareOperator, rule.CompareOperator);
            }


            [Test]
            public void Simple2()
            {
                var rule = new CompareRule<string>(expectedValueToCompare, expectedCompareOperator);
                Assert.AreEqual(expectedValueToCompare, rule.ValueToCompare);
                Assert.AreEqual(expectedCompareOperator, rule.CompareOperator);
            }


            [Test]
            public void Simple3()
            {
                var rule = new CompareRule<string>(expectedValueToCompare, expectedCompareOperator);
                Assert.AreEqual(expectedValueToCompare, rule.ValueToCompare);
                Assert.AreEqual(expectedCompareOperator, rule.CompareOperator);
                Assert.IsNull(rule.ErrorMessage);
                Assert.IsFalse(rule.UseErrorMessageProvider);
            }

            [Test]
            [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null.\r\nParameter name: valueToCompare")]
            public void ExceptionNullValueToCompare1()
            {
                new CompareRule<string>(null, CompareOperator.GreaterThan);
            }

            [Test]
            [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null.\r\nParameter name: valueToCompare")]
            public void ExceptionNullValueToCompare3()
            {
                new CompareRule<string>(null, expectedCompareOperator);
            }
            [Test]
            [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = "Value cannot be null.\r\nParameter name: valueToCompare")]
            public void ExceptionNullValueToCompare2()
            {
                new CompareRule<string>(null, expectedCompareOperator);
            }
           

        }
        [TestFixture]
        public class IsEquivalent
        {
            [Test]
            public void Simple()
            {
                var rule1 = new CompareRule<string>("aaa", CompareOperator.LessThan);
                var rule2 = new CompareRule<string>("aaa", CompareOperator.LessThan);

                Assert.IsTrue(rule1.IsEquivalent(rule2));

                rule1 = new CompareRule<string>("aaa", CompareOperator.LessThan);
                rule2 = new CompareRule<string>("aaa", CompareOperator.GreaterThanEqual);
                Assert.IsFalse(rule1.IsEquivalent(rule2));

                rule1 = new CompareRule<string>("bbb", CompareOperator.LessThan);
                rule2 = new CompareRule<string>("aaa", CompareOperator.LessThanEqual);
                Assert.IsFalse(rule1.IsEquivalent(rule2));

            }
        }


        [TestFixture]
        public class RuleInterpretation
        {
            [Test]
            public void Simple()
            {
                var rule = new CompareRule<string>(expectedValueToCompare, CompareOperator.GreaterThan);
                Assert.IsFalse(string.IsNullOrEmpty(rule.RuleInterpretation));
            }
        }
        [TestFixture]
        public class Validate
        {
            [Test]
            public void GreaterThan()
            {
                var rule = new CompareRule<string>("b", CompareOperator.GreaterThan);
                Assert.IsTrue(rule.Validate(null, null, null, null));
                Assert.IsFalse(rule.Validate(null, string.Empty, null, null));
                Assert.IsFalse(rule.Validate(null, "a", null, null));
                Assert.IsFalse(rule.Validate(null, "b", null, null));
                Assert.IsTrue(rule.Validate(null, "c", null, null));
            }

            [Test]
            public void Equal()
            {
                var rule = new CompareRule<string>("b", CompareOperator.Equal);
                Assert.IsTrue(rule.Validate(null, null, null, null));
                Assert.IsFalse(rule.Validate(null, string.Empty, null, null));
                Assert.IsFalse(rule.Validate(null, "a", null, null));
                Assert.IsTrue(rule.Validate(null, "b", null, null));
                Assert.IsFalse(rule.Validate(null, "c", null, null));
            }

            [Test]
            public void GreaterThanEqual()
            {
                var rule = new CompareRule<string>("b", CompareOperator.GreaterThanEqual);
                Assert.IsTrue(rule.Validate(null, null, null, null));
                Assert.IsFalse(rule.Validate(null, string.Empty, null, null));
                Assert.IsFalse(rule.Validate(null, "a", null, null));
                Assert.IsTrue(rule.Validate(null, "b", null, null));
                Assert.IsTrue(rule.Validate(null, "c", null, null));
            }


            [Test]
            public void GreaterThanEqualInt()
            {
                var rule = new CompareRule<int>(0, CompareOperator.GreaterThanEqual);
                Assert.IsTrue(rule.Validate(null, null, null, null));
                Assert.IsTrue(rule.Validate(null, 1, null, null));
                Assert.IsTrue(rule.Validate(null, 0, null, null));
                Assert.IsFalse(rule.Validate(null, -1, null, null));
                Assert.IsFalse(rule.Validate(null, -9, null, null));
            }

            [Test]
            public void LessThan()
            {
                var rule = new CompareRule<string>("b", CompareOperator.LessThan);
                Assert.IsTrue(rule.Validate(null, null, null, null));
                Assert.IsTrue(rule.Validate(null, string.Empty, null, null));
                Assert.IsTrue(rule.Validate(null, "a", null, null));
                Assert.IsFalse(rule.Validate(null, "b", null, null));
                Assert.IsFalse(rule.Validate(null, "c", null, null));
            }

            [Test]
            public void LessThanEqual()
            {
                var rule = new CompareRule<string>("b", CompareOperator.LessThanEqual);
                Assert.IsTrue(rule.Validate(null, null, null, null));
                Assert.IsTrue(rule.Validate(null, string.Empty, null, null));
                Assert.IsTrue(rule.Validate(null, "a", null, null));
                Assert.IsTrue(rule.Validate(null, "b", null, null));
                Assert.IsFalse(rule.Validate(null, "c", null, null));
            }

            [Test]
            public void NotEqual()
            {
                var rule = new CompareRule<string>("b", CompareOperator.NotEqual);
                Assert.IsTrue(rule.Validate(null, null, null, null));
                Assert.IsTrue(rule.Validate(null, string.Empty, null, null));
                Assert.IsTrue(rule.Validate(null, "a", null, null));
                Assert.IsFalse(rule.Validate(null, "b", null, null));
                Assert.IsTrue(rule.Validate(null, "c", null, null));
            }
        }
#if (!WindowsCE && !SILVERLIGHT)
        [TestFixture]
        public class GetBaseValidator
        {

            [Test]
            public void Simple()
            {
                var rule = new CompareRule<string>(expectedValueToCompare, CompareOperator.GreaterThan);
                var infoDescriptor = new MockInfoDescriptor(typeof(string).TypeHandle, "foo");
                rule.CheckType(infoDescriptor );
                var ruleContext = new RuleContext {Rule = rule, InfoDescriptor = infoDescriptor};
                var list = BaseValidatorGenerator.Strategies.FindStrategy(ruleContext).CreateWebClientValidators(rule, infoDescriptor);
                Assert.IsNotNull(list);
                Assert.AreEqual(1, list.Count);
            }
        }
#endif
        [TestFixture]
        public class CheckTypes
        {

            [Test]
            public void Simple()
            {
                var rule = new CompareRule<string>("expectedValueToCompare", CompareOperator.GreaterThan);
                rule.CheckType(new MockInfoDescriptor(TypePointers.StringTypeHandle, "foo"));
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Member 'foo' must be a 'System.String' to be used for the ValidationFramework.CompareRule<System.String>. Actual Type 'System.Int32'.\r\nParameter name: value")]
            public void ExceptionIncorrectType()
            {
                var rule = new CompareRule<string>("expectedValueToCompare", CompareOperator.GreaterThan);
                rule.CheckType(new MockInfoDescriptor(TypePointers.IntTypeHandle, "foo"));
            }
        }
    }
}